#include <iostream>
#include <fstream>
#include <iomanip>

#include <fcntl.h>

#include "IOError.h"
#include "Counter_DL636G1.h"
#include "DigitalIO_DL636F.h"
#include "ADC_DL642A.h"

using namespace std;

unsigned int measuretime=10, cycletime=2;
char *rawfnb = "raw";     // RAW data File Name Base
char *histfnb = "hist";   // HISTogramm data File Name Base
char *fnext = "dat";      // filename ext
char *rawfn, *histfn;     // filenames for raw data and history

void build_fn();
void show_help(char *progname);
int cmdlineargs(int argc,char *argv[]);

/*---------------------------------------------------------------------------*/
int main(int argc, char *argv[])
/*---------------------------------------------------------------------------*/
{
  const char *device="/tmp/sis1100_00remote";
  int crate;

  cerr << "testseq 0.0" << endl << endl;  

  cmdlineargs(argc,argv); build_fn();
  cerr << "rawfn: " << rawfn << endl;
  cerr << "histfn: " << histfn << endl << endl;

  cerr << "sending sequences of test pulses" << endl;

  // open files for writing
  ofstream raws(rawfn);
  ofstream hists(histfn);
  if(!raws) { cerr << "error: could not open " << rawfn << endl; exit(1); }
  if(!hists) { cerr << "error: could not open " << histfn << endl; exit(1); }
    
  // open sis1100/3100 pci-to-vme link
  if( !(crate=open(device, O_RDWR, 0)) )
  {
    cerr << "ERROR: could not open \"" << device << "\"" << endl;
    exit(1);
  }
  
  vmesysreset(crate);

  // instantiate adc object
  ADC_DL642A adc1(crate,0xb000);

  try {
    // init adc1
    cerr << "adc1: init" << endl;
    adc1.reset();
    adc1.clearFIFO();
    adc1.setEnabled(1);

    // display current state of adc1
    cerr << "adc:"
	 << " hitcounter = " << adc1.getHitCounter()
	 << " enable = " << adc1.isEnabled() 
         << " status = " << setw(4) << setfill('0') << adc1.getStatus()
         << endl << adc1.getStatusString()
	 << endl;
   
    // enable measurement through O1 of io1

    // clear histogramm
    // adc has 3 x 2^14 = 3 x 16384 channels
    u_int16_t histogramm[3][16384];
    for(int i=0; i<16384; i++)
      for(int j=0; j<3; j++ ) { histogramm[j][i] = 0; }

    cerr << "sending test sequences..." << endl;

   u_int16_t start=4,end=4,pulse=2;
    for(int i=0; i<200; i++)
      for(int j=2; j<64; j++) {
  	pulse=2;
	adc1.setTestSeq(start,pulse,end);
	adc1.startTestSeq();
	cerr << "i="<< i
	     << " sent " 
	     << start<<", "
	     << pulse << ", "
	     << end << " sleep 10us" << endl;
	usleep(10);
      }

    // display current state of adc1
    u_int32_t hitcounter = adc1.getHitCounter();
    cerr << "adc:"
	 << " hitcounter = " << hitcounter
	 << " enable = " << adc1.isEnabled() 
         << " status = " << setw(4) << setfill('0') << adc1.getStatus()
         << endl << adc1.getStatusString()
	 << endl;

    u_int32_t readcounter = 0;
    for(unsigned int i=0; i<hitcounter; i++) {
      raws << readcounter;

      for(unsigned int j=0; j<3; j++ ) {
	u_int16_t d = adc1.readFIFO32(j);
	raws << " " << d;
	histogramm[j][ d ]++; 
      }
      readcounter++;

      raws << endl;
    }

    // output histgramm data
    for(int i=0; i<16384; i++) {
      hists << i;
      for(int j=0; j<3; j++ )
	hists << " " << histogramm[j][i];
      hists << endl;
    }
       
  }
  catch( IOError ioe ) {
    cerr << "catched IOError expection: " << ioe.getMsg() << endl 
	 << "param=" << ioe.getParam() << endl << endl;

    cerr << "trying to read status of used components:" << endl << endl 
         << "adc1.hitcounter: " << adc1.getHitCounter() << endl;
  }
    
  close(crate);

  hists.close();
  raws.close();

  return 0;
}
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
void show_help(char *progname)
/*---------------------------------------------------------------------------*/
{
  cerr << "usage: " << progname << " [options]" << endl
       << endl
       << "options:" << endl
       << " -?         shows this help" << endl
       << " -r <base>  use <base> as base for raw-data file name" << endl
       << " -h <base>  use <base> as base for histogram file name" << endl
       << " -t <time>  set measure time to <time> seconds" << endl
       << " -c <time>  set cycle time to <time> seconds" << endl
       << endl;
}
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
void build_fn()
/*---------------------------------------------------------------------------*/
{
  char tmp[1024];
  time_t dummy; time(&dummy);
  strftime(tmp, 1023, "_%y%m%d_%H%M.", localtime(&dummy) );
  rawfn = new char[ strlen(rawfnb) + strlen(tmp) + strlen(fnext) + 1 ];
  strcpy(rawfn,rawfnb); strcat(rawfn,tmp); strcat(rawfn,fnext);
  histfn = new char[ strlen(histfnb) + strlen(tmp) + strlen(fnext) + 1 ];
  strcpy(histfn,histfnb); strcat(histfn,tmp); strcat(histfn,fnext);
}
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
int cmdlineargs(int argc,char *argv[])
/*---------------------------------------------------------------------------*/
{
    char c;

    opterr = 0;
     
    while( (c = getopt (argc, argv, "?r:h:t:c:") ) != -1)
	switch (c) {
	    case '?':
	      show_help(argv[0]); exit(0);
	      break;

	    case 'r':
	      if(!(rawfnb = new char[strlen(optarg)+1])) {
		cerr << "error: cmdlineargs(): could not allocate memory"
		     << endl;
		exit(1);
	      }
	      strcpy(rawfnb,optarg);
	      break;

	    case 'h':
	      if(!(histfnb = new char[strlen(optarg)+1])) {
		cerr << "error: cmdlineargs(): could not allocate memory"
		     << endl;
		exit(1);
	      }
	      strcpy(histfnb,optarg);
	      break;

	    default:
	      abort();
	}

    return 0;
}
/*---------------------------------------------------------------------------*/
